package com.wlyuan.open.application.translator;

import com.wlyuan.core.domain.MappingIds;
import com.wlyuan.core.marker.MappingStatus;
import com.wlyuan.open.domain.api.OpenApi;
import com.wlyuan.open.domain.api.OpenApiInfo;
import com.wlyuan.open.domain.api.utils.MappingOpenApiInfo;
import com.wlyuan.open.domain.api.valueobj.OpenApiId;
import com.wlyuan.open.domain.client.OpenClient;
import com.wlyuan.open.domain.client.OpenClientId;
import com.wlyuan.open.vo.OpenApiCompanyDetailVO;
import lombok.var;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Mappings;
import org.mapstruct.factory.Mappers;
import org.springframework.util.CollectionUtils;

import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * @author yuanzheng
 */
public class OpenApiInfoTranslator {

    @Mapper(uses = {MappingIds.class, MappingOpenApiInfo.class, MappingStatus.class})
    public interface Translator {

        @Mappings({
                @Mapping(source = "clientId", target = "clientId"),
                @Mapping(source = "apiId", target = "apiId"),
                @Mapping(constant = "-1", target = "totalNum"),
        })
        OpenApiInfo translate(Long clientId, Long apiId);

        @Mappings({
                @Mapping(source = "status", target = "statusName"),
                @Mapping(source = "id", target = "applyId"),
        })
        OpenApiCompanyDetailVO translate(OpenApiInfo source);

    }

    private static final Translator TRANSLATOR = Mappers.getMapper(Translator.class);

    public static List<OpenApiCompanyDetailVO> translate(List<OpenApiInfo> source) {
        if (CollectionUtils.isEmpty(source)) {
            return Collections.emptyList();
        }
        return source.stream().map(OpenApiInfoTranslator::translate).collect(Collectors.toList());
    }

    public static OpenApiCompanyDetailVO translate(OpenApiInfo source) {
        var translator = TRANSLATOR.translate(source);
        Optional.ofNullable(translator).ifPresent(t -> {
            t.setHasUse(source.hasUse());
            t.setHasEnable(source.hasEnable());
        });
        return translator;
    }

    public static List<OpenApiCompanyDetailVO> translate(List<OpenApiInfo> source, Map<OpenClientId, OpenClient> clientMap, Map<OpenApiId, OpenApi> apiMap) {
        if (CollectionUtils.isEmpty(source)) {
            return Collections.emptyList();
        }
        return source.stream().map(OpenApiInfoTranslator::translate)
                .peek(c -> c.setClientName(Optional.ofNullable(clientMap.get(new OpenClientId(c.getClientId()))).map(OpenClient::getName).orElse("")))
                .peek(a -> {
                    var openApi = apiMap.get(new OpenApiId(a.getApiId()));
                    Optional.ofNullable(openApi).ifPresent(api -> {
                        a.setApiName(api.getName());
                        a.setApiUrl(api.getUrl());
                        a.setApiRemark(api.getRemark());
                    });
                })
                .collect(Collectors.toList());
    }

    public static OpenApiInfo translate(Long clientId, Long apiId) {
        return TRANSLATOR.translate(clientId, apiId);
    }
}
